import { ColorSource, Container, Graphics, Point, Prepare } from "pixi.js";

const boneColor = 0xa4a4a5;
const boneHoverColor = 0xffffff;
const boneSelectedColor = 0x46d7db;
const ringWidth = 5;

class BoneView extends Graphics {
    public tailPos: Point = new Point(0, 0);
    public arrow: Graphics;
    public stage: Container;
    public arrowLength = 0;
    public curColor: ColorSource;

    constructor(stage: Container, x: number, y: number) {
        super();

        this.stage = stage;
        this.curColor = boneColor;

        //let graphics = new Graphics()
        this.lineStyle(/*border width*/ringWidth,/*border color*/ boneColor, 1);
        this.beginFill(0xffffff, 0.01);
        this.drawCircle(0, 0, 20);
        this.endFill();
        this.position.set(x, y);

        let arrow = new Graphics();
        this.arrow = arrow;
        arrow.lineStyle(/*border width*/1,/*border color*/ 0x0, 1);
        arrow.beginFill(0xffffff);
        arrow.drawPolygon([
            new Point(0, 0),             //First point
            new Point(10, 5),              //Second point
            new Point(20, 0),           //Third point
            new Point(10, -5),
        ]);

        // // //Fill shape's color
        arrow.endFill();
        arrow.tint = boneColor;
        this.addChild(arrow);
    }

    private _drawArrow(color: ColorSource): void {
        this.arrow.clear();
        this.arrow.lineStyle(/*border width*/1,/*border color*/ 0x0, 1);
        this.arrow.beginFill(0xffffff);
        let dist = Math.sqrt(Math.pow((this.tailPos.x - this.position.x), 2) + Math.pow((this.tailPos.y - this.position.y), 2));
        let rotation = Math.atan2((this.tailPos.y - this.position.y), (this.tailPos.x - this.position.x));
        let p1: Point;
        let p2: Point;
        let p3: Point;
        let p4: Point;
        if (dist <= 20) {
            p1 = new Point(0, 0);
            p2 = new Point(10, 5);
            p3 = new Point(20, 0);
            p4 = new Point(10, -5);
        } else {
            p1 = new Point(0, 0);
            p2 = new Point(20, 10);
            p3 = new Point(dist, 0);
            p4 = new Point(20, -10);
        }
        this.arrow.drawPolygon([p1, p2, p3, p4]);

        this.arrow.endFill();
        this.arrow.tint = color;
        this.rotation = rotation;
        this.arrowLength = dist;
    }

    public updateArrowLength(length: number) {
        this.arrow.clear();
        this.arrow.lineStyle(/*border width*/1,/*border color*/ 0x0, 1);
        this.arrow.beginFill(0xffffff);
        let p1: Point;
        let p2: Point;
        let p3: Point;
        let p4: Point;
        if (length <= 20) {
            p1 = new Point(0, 0);
            p2 = new Point(10, 5);
            p3 = new Point(20, 0);
            p4 = new Point(10, -5);
        } else {
            p1 = new Point(0, 0);
            p2 = new Point(20, 10);
            p3 = new Point(length, 0);
            p4 = new Point(20, -10);
        }
        this.arrow.drawPolygon([p1, p2, p3, p4]);

        this.arrow.endFill();
        this.arrow.tint = this.curColor;
        this.arrowLength = length;
    }

    public updateTail(x: number, y: number): void {
        this.tailPos.x = x;
        this.tailPos.y = y;
        this._drawArrow(this.curColor);
    }

    public isContainPoint(point: Point): boolean {
        return this.containsPoint(point) || this.arrow.containsPoint(point);
    }

    public selected(state: boolean) {
        if (state == true) {
            //this._drawArrow("blue");
            this.arrow.tint = boneSelectedColor;
            this.curColor = boneSelectedColor;
        } else {
            //this._drawArrow(0x66FF33);
            this.arrow.tint = boneColor;
            this.curColor = boneColor;
        }
    }

    public rotateBetweenPoint(from: Point, to: Point) {
        let rotationTo = Math.atan2((to.y - this.position.y), (to.x - this.position.x));
        let rotationFrom = Math.atan2((from.y - this.position.y), (from.x - this.position.x));
        let rotation = rotationTo - rotationFrom;
        this.rotation += rotation;

        // x = (x1 - x2) * cos(θ) + (y1 - y2) * sin(θ) + x2
        // y = (y1 - y2) * cos(θ) - (x1 - x2) * sin(θ) + y2
        // let newTailX = (this.tailPos.x - this.origin.x) * Math.cos(rotation) + (this.tailPos.y - this.origin.y) * Math.sin(rotation) + this.origin.x;
        // let newTailY = (this.tailPos.y - this.origin.y) * Math.cos(rotation) - (this.tailPos.x - this.origin.x) * Math.sin(rotation) + this.origin.y;
        // this.tailPos.x = newTailX;
        // this.tailPos.y = newTailY;
    }

    public getTailPoint(): Point {
        let tailX = this.position.x + this.localTransform.a * this.arrowLength;
        let tailY = this.position.y + this.localTransform.b * this.arrowLength;
        return new Point(tailX, tailY);
    }

    public hoverEnter() {
        this.arrow.tint = boneHoverColor;
        this.curColor = boneHoverColor;

    }

    public hoverLeave() {
        this.arrow.tint = boneColor;
        this.curColor = boneColor;
    }

    // get localTransformWithGlobalPos() {
    //     const parent = this.parent as Viewport;
    //     const transform = this.localTransform;
    //     const gPos = parent.toGlobal(new Point(transform.tx, transform.ty));
    //     transform.tx = gPos.x;
    //     transform.ty = gPos.y;
    //     return transform;
    // }
}

export { BoneView };